home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 45
/
Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso
/
Aminet
/
gfx
/
x11
/
x3270_3_2_16.lha
/
amiga_src
/
sf.c
< prev
next >
Wrap
C/C++ Source or Header
|
2008-12-15
|
18KB
|
765 lines
/*
* Copyright 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*/
/*
* sf.c
* This module handles 3270 structured fields.
*
*/
#include "globals.h"
#include <errno.h>
#include "3270ds.h"
#include "appres.h"
#include "screen.h"
#include "cg.h"
#include "ctlr.h"
#include "resources.h"
#include "ctlrc.h"
#if defined(X3270_FT) /*[*/
#include "ft_dftc.h"
#endif /*]*/
#include "kybdc.h"
#include "screenc.h"
#include "sfc.h"
#include "telnetc.h"
#include "trace_dsc.h"
#include "utilc.h"
/* Externals: ctlr.c */
extern Boolean screen_alt;
extern unsigned char reply_mode;
extern int crm_nattr;
extern unsigned char crm_attr[];
/* Statics */
static Boolean qr_in_progress = False;
static enum pds sf_read_part(unsigned char buf[], unsigned buflen);
static enum pds sf_erase_reset(unsigned char buf[], int buflen);
static enum pds sf_set_reply_mode(unsigned char buf[], int buflen);
static enum pds sf_create_partition(unsigned char buf[], int buflen);
static enum pds sf_outbound_ds(unsigned char buf[], int buflen);
static void query_reply_start(void);
static void do_query_reply(unsigned char code);
static void query_reply_end(void);
static unsigned char supported_replies[] = {
QR_SUMMARY, /* 0x80 */
QR_USABLE_AREA, /* 0x81 */
QR_ALPHA_PART, /* 0x84 */
QR_CHARSETS, /* 0x85 */
QR_COLOR, /* 0x86 */
QR_HIGHLIGHTING, /* 0x87 */
QR_REPLY_MODES, /* 0x88 */
QR_IMP_PART, /* 0xa6 */
#if defined(X3270_FT) /*[*/
QR_DDM, /* 0x95 */
#endif /*]*/
};
#define NSR (sizeof(supported_replies)/sizeof(unsigned char))
/*
* Process a 3270 Write Structured Field command
*/
enum pds
write_structured_field(unsigned char buf[], int buflen)
{
unsigned short fieldlen;
unsigned char *cp = buf;
Boolean first = True;
enum pds rv = PDS_OKAY_NO_OUTPUT;
enum pds rv_this = PDS_OKAY_NO_OUTPUT;
Boolean bad_cmd = False;
/* Skip the WSF command itself. */
cp++;
buflen--;
/* Interpret fields. */
while (buflen > 0) {
if (first)
trace_ds(" ");
else
trace_ds("< WriteStructuredField ");
first = False;
/* Pick out the field length. */
if (buflen < 2) {
trace_ds("error: single byte at end of message\n");
return rv ? rv : PDS_BAD_CMD;
}
fieldlen = (cp[0] << 8) + cp[1];
if (fieldlen == 0)
fieldlen = buflen;
if (fieldlen < 3) {
trace_ds("error: field length %d too small\n",
fieldlen);
return rv ? rv : PDS_BAD_CMD;
}
if ((int)fieldlen > buflen) {
trace_ds("error: field length %d exceeds remaining "
"message length %d\n",
fieldlen, buflen);
return rv ? rv : PDS_BAD_CMD;
}
/* Dispatch on the ID. */
switch (cp[2]) {
case SF_READ_PART:
trace_ds("ReadPartition");
rv_this = sf_read_part(cp, (int)fieldlen);
break;
case SF_ERASE_RESET:
trace_ds("EraseReset");
rv_this = sf_erase_reset(cp, (int)fieldlen);
break;
case SF_SET_REPLY_MODE:
trace_ds("SetReplyMode");
rv_this = sf_set_reply_mode(cp, (int)fieldlen);
break;
case SF_CREATE_PART:
trace_ds("CreatePartition");
rv_this = sf_create_partition(cp, (int)fieldlen);
break;
case SF_OUTBOUND_DS:
trace_ds("OutboundDS");
rv_this = sf_outbound_ds(cp, (int)fieldlen);
break;
#if defined(X3270_FT) /*[*/
case SF_TRANSFER_DATA: /* File transfer data */
trace_ds("FileTransferData");
ft_dft_data(cp, (int)fieldlen);
break;
#endif /*]*/
default:
trace_ds("unsupported ID 0x%02x\n", cp[2]);
rv_this = PDS_BAD_CMD;
break;
}
/*
* Accumulate errors or output flags.
* One real ugliness here is that if we have already
* generated some output, then we have already positively
* acknowledged the request, so if we fail here, we have no
* way to return the error indication.
*/
if (rv_this < 0)
bad_cmd = True;
else
rv |= rv_this;
/* Skip to the next field. */
cp += fieldlen;
buflen -= fieldlen;
}
if (first)
trace_ds(" (null)\n");
if (bad_cmd && !rv)
return PDS_BAD_CMD;
else
return rv;
}
static enum pds
sf_read_part(unsigned char buf[], unsigned buflen)
{
unsigned char partition;
unsigned i;
int any = 0;
const char *comma = "";
if (buflen < 5) {
trace_ds(" error: field length %d too small\n", buflen);
return PDS_BAD_CMD;
}
partition = buf[3];
trace_ds("(0x%02x)", partition);
switch (buf[4]) {
case SF_RP_QUERY:
trace_ds(" Query");
if (partition != 0xff) {
trace_ds(" error: illegal partition\n");
return PDS_BAD_CMD;
}
trace_ds("\n");
query_reply_start();
for (i = 0; i < NSR; i++)
do_query_reply(supported_replies[i]);
query_reply_end();
break;
case SF_RP_QLIST:
trace_ds(" QueryList ");
if (partition != 0xff) {
trace_ds("error: illegal partition\n");
return PDS_BAD_CMD;
}
if (buflen < 6) {
trace_ds("error: missing request type\n");
return PDS_BAD_CMD;
}
query_reply_start();
switch (buf[5]) {
case SF_RPQ_LIST:
trace_ds("List(");
if (buflen < 7) {
trace_ds(")\n");
do_query_reply(QR_NULL);
} else {
for (i = 6; i < buflen; i++) {
trace_ds("%s%s", comma,
see_qcode(buf[i]));
comma = ",";
}
trace_ds(")\n");
for (i = 0; i < NSR; i++) {
if (memchr((char *)&buf[6],
(char)supported_replies[i],
buflen-6)) {
do_query_reply(supported_replies[i]);
any++;
}
}
if (!any) {
do_query_reply(QR_NULL);
}
}
break;
case SF_RPQ_EQUIV:
trace_ds("Equivlent+List(");
for (i = 6; i < buflen; i++) {
trace_ds("%s%s", comma, see_qcode(buf[i]));
comma = ",";
}
trace_ds(")\n");
for (i = 0; i < NSR; i++)
do_query_reply(supported_replies[i]);
break;
case SF_RPQ_ALL:
trace_ds("All\n");
for (i = 0; i < NSR; i++)
do_query_reply(supported_replies[i]);
break;
default:
trace_ds("unknown request type 0x%02x\n", buf[5]);
return PDS_BAD_CMD;
}
query_reply_end();
break;
case SNA_CMD_RMA:
trace_ds(" ReadModifiedAll");
if (partition != 0x00) {
trace_ds(" error: illegal partition\n");
return PDS_BAD_CMD;
}
trace_ds("\n");
ctlr_read_modified(AID_QREPLY, True);
break;
case SNA_CMD_RB:
trace_ds(" ReadBuffer");
if (partition != 0x00) {
trace_ds(" error: illegal partition\n");
return PDS_BAD_CMD;
}
trace_ds("\n");
ctlr_read_buffer(AID_QREPLY);
break;
case SNA_CMD_RM:
trace_ds(" ReadModified");
if (partition != 0x00) {
trace_ds(" error: illegal partition\n");
return PDS_BAD_CMD;
}
trace_ds("\n");
ctlr_read_modified(AID_QREPLY, False);
break;
default:
trace_ds(" unknown type 0x%02x\n", buf[4]);
return PDS_BAD_CMD;
}
return PDS_OKAY_OUTPUT;
}
static enum pds
sf_erase_reset(unsigned char buf[], int buflen)
{
if (buflen != 4) {
trace_ds(" error: wrong field length %d\n", buflen);
return PDS_BAD_CMD;
}
switch (buf[3]) {
case SF_ER_DEFAULT:
trace_ds(" Default\n");
ctlr_erase(False);
break;
case SF_ER_ALT:
trace_ds(" Alternate\n");
ctlr_erase(True);
break;
default:
trace_ds(" unknown type 0x%02x\n", buf[3]);
return PDS_BAD_CMD;
}
return PDS_OKAY_NO_OUTPUT;
}
static enum pds
sf_set_reply_mode(unsigned char buf[], int buflen)
{
unsigned char partition;
int i;
const char *comma = "(";
if (buflen < 5) {
trace_ds(" error: wrong field length %d\n", buflen);
return PDS_BAD_CMD;
}
partition = buf[3];
trace_ds("(0x%02x)", partition);
if (partition != 0x00) {
trace_ds(" error: illegal partition\n");
return PDS_BAD_CMD;
}
switch (buf[4]) {
case SF_SRM_FIELD:
trace_ds(" Field\n");
break;
case SF_SRM_XFIELD:
trace_ds(" ExtendedField\n");
break;
case SF_SRM_CHAR:
trace_ds(" Character");
break;
default:
trace_ds(" unknown mode 0x%02x\n", buf[4]);
return PDS_BAD_CMD;
}
reply_mode = buf[4];
if (buf[4] == SF_SRM_CHAR) {
crm_nattr = buflen - 5;
for (i = 5; i < buflen; i++) {
crm_attr[i - 5] = buf[i];
trace_ds("%s%s", comma, see_efa_only(buf[i]));
comma = ",";
}
trace_ds("%s\n", crm_nattr ? ")" : "");
}
return PDS_OKAY_NO_OUTPUT;
}
static enum pds
sf_create_partition(unsigned char buf[], int buflen)
{
unsigned char pid;
unsigned char uom; /* unit of measure */
unsigned char am; /* addressing mode */
unsigned char flags; /* flags */
unsigned short h; /* height of presentation space */
unsigned short w; /* width of presentation space */
unsigned short rv; /* viewport origin row */
unsigned short cv; /* viewport origin column */
unsigned short hv; /* viewport height */
unsigned short wv; /* viewport width */
unsigned short rw; /* window origin row */
unsigned short cw; /* window origin column */
unsigned short rs; /* scroll rows */
/* hole */
unsigned short pw; /* character cell point width */
unsigned short ph; /* character cell point height */
static const char *bit4[16] = {
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
};
if (buflen > 3) {
trace_ds("(");
/* Partition. */
pid = buf[3];
trace_ds("pid=0x%02x", pid);
if (pid != 0x00) {
trace_ds(") error: illegal partition\n");
return PDS_BAD_CMD;
}
} else
pid = 0x00;
if (buflen > 4) {
uom = (buf[4] & 0xf0) >> 4;
trace_ds(",uom=B'%s'", bit4[uom]);
if (uom != 0x0 && uom != 0x02) {
trace_ds(") error: illegal units\n");
return PDS_BAD_CMD;
}
am = buf[4] & 0x0f;
trace_ds(",am=B'%s'", bit4[am]);
if (am > 0x2) {
trace_ds(") error: illegal a-mode\n");
return PDS_BAD_CMD;
}
} else {
uom = 0;
am = 0;
}
if (buflen > 5) {
flags = buf[5];
trace_ds(",flags=0x%02x", flags);
} else
flags = 0;
if (buflen > 7) {
GET16(h, &buf[6]);
trace_ds(",h=%d", h);
} else
h = maxROWS;
if (buflen > 9) {
GET16(w, &buf[8]);
trace_ds(",w=%d", w);
} else
w = maxCOLS;
if (buflen > 11) {
GET16(rv, &buf[10]);
trace_ds(",rv=%d", rv);
} else
rv = 0;
if (buflen > 13) {
GET16(cv, &buf[12]);
trace_ds(",cv=%d", cv);
} else
cv = 0;
if (buflen > 15) {
GET16(hv, &buf[14]);
trace_ds(",hv=%d", hv);
} else
hv = (h > maxROWS)? maxROWS: h;
if (buflen > 17) {
GET16(wv, &buf[16]);
trace_ds(",wv=%d", wv);
} else
wv = (w > maxCOLS)? maxCOLS: w;
if (buflen > 19) {
GET16(rw, &buf[18]);
trace_ds(",rw=%d", rw);
} else
rw = 0;
if (buflen > 21) {
GET16(cw, &buf[20]);
trace_ds(",cw=%d", cw);
} else
cw = 0;
if (buflen > 23) {
GET16(rs, &buf[22]);
trace_ds(",rs=%d", rs);
} else
rs = (h > hv)? 1: 0;
if (buflen > 27) {
GET16(pw, &buf[26]);
trace_ds(",pw=%d", pw);
} else
pw = *char_width;
if (buflen > 29) {
GET16(ph, &buf[28]);
trace_ds(",ph=%d", ph);
} else
ph = *char_height;
trace_ds(")\n");
cursor_move(0);
buffer_addr = 0;
return PDS_OKAY_NO_OUTPUT;
}
static enum pds
sf_outbound_ds(unsigned char buf[], int buflen)
{
if (buflen < 5) {
trace_ds(" error: field length %d too short\n", buflen);
return PDS_BAD_CMD;
}
trace_ds("(0x%02x)", buf[3]);
if (buf[3] != 0x00) {
trace_ds(" error: illegal partition 0x%0x\n", buf[3]);
return PDS_BAD_CMD;
}
switch (buf[4]) {
case SNA_CMD_W:
trace_ds(" Write");
if (buflen > 5)
ctlr_write(&buf[4], buflen-4, False);
else
trace_ds("\n");
break;
case SNA_CMD_EW:
trace_ds(" EraseWrite");
ctlr_erase(screen_alt);
if (buflen > 5)
ctlr_write(&buf[4], buflen-4, True);
else
trace_ds("\n");
break;
case SNA_CMD_EWA:
trace_ds(" EraseWriteAlternate");
ctlr_erase(screen_alt);
if (buflen > 5)
ctlr_write(&buf[4], buflen-4, True);
else
trace_ds("\n");
break;
case SNA_CMD_EAU:
trace_ds(" EraseAllUnprotected\n");
ctlr_erase_all_unprotected();
break;
default:
trace_ds(" unknown type 0x%02x\n", buf[4]);
return PDS_BAD_CMD;
}
return PDS_OKAY_NO_OUTPUT;
}
static void
query_reply_start(void)
{
obptr = obuf;
space3270out(1);
*obptr++ = AID_SF;
qr_in_progress = True;
}
static void
do_query_reply(unsigned char code)
{
int len;
unsigned i;
const char *comma = "";
int obptr0 = obptr - obuf;
unsigned char *obptr_len;
unsigned short num, denom;
char *cp_name;
char *cp_value;
unsigned long cp;
char *ptr;
if (qr_in_progress) {
trace_ds("> StructuredField\n");
qr_in_progress = False;
}
space3270out(4);
obptr += 2; /* skip length for now */
*obptr++ = SFID_QREPLY;
*obptr++ = code;
switch (code) {
case QR_CHARSETS:
trace_ds("> QueryReply(CharacterSets)\n");
space3270out(23);
*obptr++ = 0x82; /* flags: GE, CGCSGID present */
*obptr++ = 0x00; /* more flags */
*obptr++ = *char_width; /* SDW */
*obptr++ = *char_height;/* SDH */
*obptr++ = 0x00; /* Load PS format types */
*obptr++ = 0x00;
*obptr++ = 0x00;
*obptr++ = 0x00;
*obptr++ = 0x07; /* DL */
*obptr++ = 0x00; /* SET 0: */
*obptr++ = 0x10; /* FLAGS: non-loadable, single-plane,
single-byte, no compare */
*obptr++ = 0x00; /* LCID */
*obptr++ = 0x02; /* CGCSGID: English (U.S.) */
*obptr++ = 0xb9;
/* Get the codepage resource. */
cp_name = xs_buffer("%s.%s", ResCodepage, appres.charset);
cp_value = get_resource(cp_name);
if (cp_value != CN &&
(cp = strtoul(cp_value, &ptr, 0)) &&
ptr != cp_value &&
*ptr == '\0' &&
!(cp & ~0xffffL)) {
/* Reasonable non-default value defined. */
SET16(obptr, cp);
} else {
/* Default to codepage 37. */
*obptr++ = 0x00;
*obptr++ = 0x25;
}
Free(cp_name);
if (!*standard_font) {
/* special 3270 font, includes APL */
*obptr++ = 0x01;/* SET 1: */
*obptr++ = 0x10;/* FLAGS: non-loadable, single-plane,
single-byte, no compare */
*obptr++ = 0xf1;/* LCID */
*obptr++ = 0x03;/* CGCSGID: 3179-style APL2 */
*obptr++ = 0xc3;
*obptr++ = 0x01;
*obptr++ = 0x36;
}
break;
case QR_IMP_PART:
trace_ds("> QueryReply(ImplicitPartition)\n");
space3270out(13);
*obptr++ = 0x0; /* reserved */
*obptr++ = 0x0;
*obptr++ = 0x0b; /* length of display size */
*obptr++ = 0x01; /* "implicit partition size" */
*obptr++ = 0x00; /* reserved */
SET16(obptr, 80); /* implicit partition width */
SET16(obptr, 24); /* implicit partition height */
SET16(obptr, maxCOLS); /* alternate height */
SET16(obptr, maxROWS); /* alternate width */
break;
case QR_NULL:
trace_ds("> QueryReply(Null)\n");
break;
case QR_SUMMARY:
trace_ds("> QueryReply(Summary(");
space3270out(NSR);
for (i = 0; i < NSR; i++) {
trace_ds("%s%s", comma,
see_qcode(supported_replies[i]));
comma = ",";
*obptr++ = supported_replies[i];
}
trace_ds("))\n");
break;
case QR_USABLE_AREA:
trace_ds("> QueryReply(UsableArea)\n");
space3270out(19);
*obptr++ = 0x01; /* 12/14-bit addressing */
*obptr++ = 0x00; /* no special character features */
SET16(obptr, maxCOLS); /* usable width */
SET16(obptr, maxROWS); /* usable height */
*obptr++ = 0x01; /* units (mm) */
num = display_widthMM();
denom = display_width();
while (!(num %2) && !(denom % 2)) {
num /= 2;
denom /= 2;
}
SET16(obptr, (int)num); /* Xr numerator */
SET16(obptr, (int)denom); /* Xr denominator */
num = display_heightMM();
denom = display_height();
while (!(num %2) && !(denom % 2)) {
num /= 2;
denom /= 2;
}
SET16(obptr, (int)num); /* Yr numerator */
SET16(obptr, (int)denom); /* Yr denominator */
*obptr++ = *char_width; /* AW */
*obptr++ = *char_height;/* AH */
SET16(obptr, maxCOLS*maxROWS); /* buffer, questionable */
break;
case QR_COLOR:
trace_ds("> QueryReply(Color)\n");
space3270out(4 + 2*15);
*obptr++ = 0x00; /* no options */
*obptr++ = 16; /* report on 16 colors */
*obptr++ = 0x00; /* default color: */
*obptr++ = 0xf0 + COLOR_GREEN; /* green */
for (i = 0xf1; i <= 0xff; i++) {
*obptr++ = i;
if (appres.m3279)
*obptr++ = i;
else
*obptr++ = 0x00;
}
break;
case QR_HIGHLIGHTING:
trace_ds("> QueryReply(Highlighting)\n");
space3270out(11);
*obptr++ = 5; /* report on 5 pairs */
*obptr++ = XAH_DEFAULT; /* default: */
*obptr++ = XAH_NORMAL; /* normal */
*obptr++ = XAH_BLINK; /* blink: */
*obptr++ = XAH_BLINK; /* blink */
*obptr++ = XAH_REVERSE; /* reverse: */
*obptr++ = XAH_REVERSE; /* reverse */
*obptr++ = XAH_UNDERSCORE; /* underscore: */
*obptr++ = XAH_UNDERSCORE; /* underscore */
*obptr++ = XAH_INTENSIFY; /* intensify: */
*obptr++ = XAH_INTENSIFY; /* intensify */
break;
case QR_REPLY_MODES:
trace_ds("> QueryReply(ReplyModes)\n");
space3270out(3);
*obptr++ = SF_SRM_FIELD;
*obptr++ = SF_SRM_XFIELD;
*obptr++ = SF_SRM_CHAR;
break;
case QR_ALPHA_PART:
trace_ds("> QueryReply(AlphanumericPartitions)\n");
space3270out(4);
*obptr++ = 0; /* 1 partition */
SET16(obptr, maxROWS*maxCOLS); /* buffer space */
*obptr++ = 0; /* no special features */
break;
#if defined(X3270_FT) /*[*/
case QR_DDM:
trace_ds("> QueryReply(DistributedDataManagement)\n");
space3270out(8);
SET16(obptr,0); /* set reserved field to 0 */
SET16(obptr,2048); /* set inbound length limit */
SET16(obptr,2048); /* set outbound length limit */
SET16(obptr,0x0101); /* NSS=01, DDMSS=01 */
break;
#endif /*]*/
default:
return; /* internal error */
}
obptr_len = obuf + obptr0;
len = (obptr - obuf) - obptr0;
SET16(obptr_len, len);
}
static void
query_reply_end(void)
{
net_output();
kybd_inhibit(True);
}